// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package shell

import (
	"net/http"
	"strings"

	"yunion.io/x/cloudmux/pkg/cloudprovider"
)

type ObjectHeaderOptions struct {
	CacheControl       string `help:"Cache-Control"`
	ContentType        string `help:"Content-Type"`
	ContentEncoding    string `help:"Content-Encoding"`
	ContentLanguage    string `help:"Content-Language"`
	ContentDisposition string `help:"Content-Disposition"`
	ContentMD5         string `help:"Content-MD5"`

	Meta []string `help:"header, common seperatored key and value, e.g. max-age:100"`
}

func (args ObjectHeaderOptions) Options2Header() http.Header {
	meta := http.Header{}
	for _, kv := range args.Meta {
		parts := strings.Split(kv, ":")
		if len(parts) == 2 {
			key := strings.TrimSpace(parts[0])
			value := strings.TrimSpace(parts[1])
			if len(key) > 0 && len(value) > 0 {
				meta.Add(key, value)
			}
		}
	}
	if len(args.CacheControl) > 0 {
		meta.Set(cloudprovider.META_HEADER_CACHE_CONTROL, args.CacheControl)
	}
	if len(args.ContentType) > 0 {
		meta.Set(cloudprovider.META_HEADER_CONTENT_TYPE, args.ContentType)
	}
	if len(args.ContentEncoding) > 0 {
		meta.Set(cloudprovider.META_HEADER_CONTENT_ENCODING, args.ContentEncoding)
	}
	if len(args.ContentMD5) > 0 {
		meta.Set(cloudprovider.META_HEADER_CONTENT_MD5, args.ContentMD5)
	}
	if len(args.ContentLanguage) > 0 {
		meta.Set(cloudprovider.META_HEADER_CONTENT_LANGUAGE, args.ContentLanguage)
	}
	if len(args.ContentDisposition) > 0 {
		meta.Set(cloudprovider.META_HEADER_CONTENT_DISPOSITION, args.ContentDisposition)
	}
	return meta
}

func init() {
	cmd := NewCommand("bucket")

	eR := EmptyOptionRegionR("bucket")

	eR.GetterList("list", "List all bucket", func(ir cloudprovider.ICloudRegion) (any, error) {
		return ir.GetIBuckets()
	})

	type BucketCreateOptions struct {
		NAME         string `help:"name of bucket to create"`
		Acl          string `help:"ACL string" choices:"private|public-read|public-read-write"`
		StorageClass string `help:"StorageClass"`
	}
	RegionR[BucketCreateOptions](cmd).Run("create", "Create bucket", func(cli cloudprovider.ICloudRegion, args *BucketCreateOptions) (any, error) {
		return nil, cli.CreateIBucket(args.NAME, args.StorageClass, args.Acl)
	})

	type BucketAclOptions struct {
		BUCKET string `help:"name of bucket"`
		ACL    string `help:"ACL string" choices:"private|public-read|public-read-write"`
	}
	RegionR[BucketAclOptions](cmd).Run("set-acl", "Set bucket ACL", func(cli cloudprovider.ICloudRegion, args *BucketAclOptions) (any, error) {
		bucket, err := cli.GetIBucketById(args.BUCKET)
		if err != nil {
			return nil, err
		}
		err = bucket.SetAcl(cloudprovider.TBucketACLType(args.ACL))
		if err != nil {
			return nil, err
		}
		return nil, nil
	})

	// type BucketDeleteOptions struct {
	// 	NAME string `help:"name of bucket to delete"`
	// }
	// RegionR(&BucketDeleteOptions{}, "bucket-delete", "Delete bucket", func(cli cloudprovider.ICloudRegion, args *BucketDeleteOptions) error {
	// 	err := cli.DeleteIBucket(args.NAME)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	return nil
	// })
	//
	// type BucketLimitOptions struct {
	// 	NAME    string `help:"name of bucket to set limit"`
	// 	SizeGB  int    `help:"limit of volumes in GB"`
	// 	Objects int    `help:"limit of object count"`
	// 	Off     bool   `help:"Turn off limit"`
	// }
	// RegionR(&BucketLimitOptions{}, "bucket-set-limit", "Set bucket limit", func(cli cloudprovider.ICloudRegion, args *BucketLimitOptions) error {
	// 	bucket, err := cli.GetIBucketByName(args.NAME)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	if args.Off {
	// 		err = bucket.SetLimit(cloudprovider.SBucketStats{})
	// 	} else {
	// 		fmt.Println("set limit")
	// 		err = bucket.SetLimit(cloudprovider.SBucketStats{SizeBytes: int64(args.SizeGB * 1000 * 1000 * 1000), ObjectCount: args.Objects})
	// 	}
	// 	if err != nil {
	// 		return err
	// 	}
	// 	return nil
	// })
	//
	// type BucketExistOptions struct {
	// 	NAME string `help:"name of bucket to delete"`
	// }
	// RegionR(&BucketExistOptions{}, "bucket-exist", "Test existence of a bucket", func(cli cloudprovider.ICloudRegion, args *BucketExistOptions) error {
	// 	exist, err := cli.IBucketExist(args.NAME)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Printf("Exist: %v\n", exist)
	// 	return nil
	// })
	//
	// type BucketObjectsOptions struct {
	// 	BUCKET    string `help:"name of bucket to list objects"`
	// 	Prefix    string `help:"prefix"`
	// 	Marker    string `help:"marker"`
	// 	Demiliter string `help:"delimiter"`
	// 	Max       int    `help:"Max count"`
	// }
	// RegionR(&BucketObjectsOptions{}, "bucket-object", "List objects in a bucket", func(cli cloudprovider.ICloudRegion, args *BucketObjectsOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	result, err := bucket.ListObjects(args.Prefix, args.Marker, args.Demiliter, args.Max)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	if result.IsTruncated {
	// 		fmt.Printf("NextMarker: %s IsTruncated: %v\n", result.NextMarker, result.IsTruncated)
	// 	}
	// 	fmt.Println("Common prefixes:")
	// 	PrintGetterList(result.CommonPrefixes, []string{"key", "size_bytes"})
	// 	fmt.Println("Objects:")
	// 	PrintGetterList(result.Objects, []string{"key", "size_bytes"})
	// 	return nil
	// })
	//
	// type BucketListObjectsOptions struct {
	// 	BUCKET string `help:"name of bucket to list objects"`
	// 	Prefix string `help:"prefix"`
	// 	Limit  int    `help:"limit per page request" default:"20"`
	// 	Marker string `help:"offset marker"`
	// }
	// RegionR(&BucketListObjectsOptions{}, "bucket-list-object", "List objects in a bucket", func(cli cloudprovider.ICloudRegion, args *BucketListObjectsOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	objects, marker, err := cloudprovider.GetPagedObjects(bucket, args.Prefix, true, args.Marker, args.Limit)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintGetterList(objects, []string{"key", "size_bytes"})
	// 	if len(marker) > 0 {
	// 		fmt.Println("Next marker:", marker)
	// 	}
	// 	return nil
	// })
	//
	// RegionR(&BucketListObjectsOptions{}, "bucket-dir-object", "List objects in a bucket like directory", func(cli cloudprovider.ICloudRegion, args *BucketListObjectsOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	objects, marker, err := cloudprovider.GetPagedObjects(bucket, args.Prefix, false, args.Marker, args.Limit)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintGetterList(objects, []string{"key", "size_bytes"})
	// 	if len(marker) > 0 {
	// 		fmt.Println("Next marker:", marker)
	// 	}
	// 	return nil
	// })
	//
	// type BucketMakrdirOptions struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	DIR    string `help:"dir to make"`
	// }
	// RegionR(&BucketMakrdirOptions{}, "bucket-mkdir", "Mkdir in a bucket", func(cli cloudprovider.ICloudRegion, args *BucketMakrdirOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	err = cloudprovider.Makedir(context.Background(), bucket, args.DIR)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Printf("Mkdir success\n")
	// 	return nil
	// })
	//
	// type BucketPutObjectOptions struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	KEY    string `help:"key of object"`
	// 	Path   string `help:"Path of file to upload"`
	//
	// 	BlockSize int64 `help:"blocksz in MB" default:"100"`
	//
	// 	Acl string `help:"acl" choices:"private|public-read|public-read-write"`
	//
	// 	StorageClass string `help:"storage class"`
	//
	// 	ObjectHeaderOptions
	// }
	// RegionR(&BucketPutObjectOptions{}, "put-object", "Put object into a bucket", func(cli cloudprovider.ICloudRegion, args *BucketPutObjectOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	//
	// 	originMeta := args.ObjectHeaderOptions.Options2Header()
	//
	// 	if len(args.Path) > 0 {
	// 		uploadFile := func(key, path string) error {
	// 			meta := http.Header{}
	// 			for k, v := range originMeta {
	// 				meta[k] = v
	// 			}
	//
	// 			finfo, err := os.Stat(path)
	// 			if err != nil {
	// 				return errors.Wrap(err, "os.Stat")
	// 			}
	// 			fSize := finfo.Size()
	// 			file, err := os.Open(path)
	// 			if err != nil {
	// 				return errors.Wrap(err, "os.Open")
	// 			}
	// 			defer file.Close()
	//
	// 			if contTypes, ok := meta[cloudprovider.META_HEADER_CONTENT_TYPE]; !ok || len(contTypes) == 0 {
	// 				var ext string
	// 				lastSlashPos := strings.LastIndex(path, "/")
	// 				lastExtPos := strings.LastIndex(path, ".")
	// 				if lastExtPos >= 0 && lastExtPos > lastSlashPos {
	// 					ext = path[lastExtPos:]
	// 				}
	// 				if len(ext) > 0 {
	// 					contType := mime.TypeByExtension(ext)
	// 					meta.Set(cloudprovider.META_HEADER_CONTENT_TYPE, contType)
	// 				}
	// 			}
	//
	// 			err = cloudprovider.UploadObject(context.Background(), bucket, key, args.BlockSize*1000*1000, file, fSize, cloudprovider.TBucketACLType(args.Acl), args.StorageClass, meta, true)
	// 			if err != nil {
	// 				return err
	// 			}
	//
	// 			return nil
	// 		}
	// 		if fileutils2.IsFile(args.Path) {
	// 			err := uploadFile(args.KEY, args.Path)
	// 			if err != nil {
	// 				return errors.Wrap(err, "uploadFile")
	// 			}
	// 		} else if fileutils2.IsDir(args.Path) {
	// 			return filepath.Walk(args.Path, func(path string, info os.FileInfo, err error) error {
	// 				if err != nil {
	// 					return err
	// 				}
	// 				if info.Mode().IsRegular() {
	// 					rel, _ := filepath.Rel(args.Path, path)
	// 					src := path
	// 					dst := filepath.Join(args.KEY, rel)
	// 					fmt.Println("upload", src, "to", dst)
	// 					uploadErr := uploadFile(dst, src)
	// 					if uploadErr != nil {
	// 						return uploadErr
	// 					}
	// 				}
	// 				return nil
	// 			})
	// 		}
	// 	} else {
	// 		err = cloudprovider.UploadObject(context.Background(), bucket, args.KEY, args.BlockSize*1000*1000, os.Stdin, 0, cloudprovider.TBucketACLType(args.Acl), args.StorageClass, originMeta, true)
	// 		if err != nil {
	// 			return err
	// 		}
	// 	}
	//
	// 	fmt.Printf("Upload success\n")
	// 	return nil
	// })
	//
	// type BucketDeleteObjectOptions struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	KEY    string `help:"key of object"`
	// }
	// RegionR(&BucketDeleteObjectOptions{}, "delete-object", "Delete object from a bucket", func(cli cloudprovider.ICloudRegion, args *BucketDeleteObjectOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	err = bucket.DeleteObject(context.Background(), args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Printf("Delete success\n")
	// 	return nil
	// })
	//
	// RegionR(&BucketDeleteObjectOptions{}, "delete-prefix", "Delete object from a bucket", func(cli cloudprovider.ICloudRegion, args *BucketDeleteObjectOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	err = cloudprovider.DeletePrefix(context.Background(), bucket, args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Printf("Delete success\n")
	// 	return nil
	// })
	//
	// type BucketTempUrlOption struct {
	// 	BUCKET   string `help:"name of bucket to put object"`
	// 	METHOD   string `help:"http method" choices:"GET|PUT|DELETE"`
	// 	KEY      string `help:"key of object"`
	// 	Duration int    `help:"duration in seconds" default:"60"`
	// }
	// RegionR(&BucketTempUrlOption{}, "temp-url", "generate temp url", func(cli cloudprovider.ICloudRegion, args *BucketTempUrlOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	urlStr, err := bucket.GetTempUrl(args.METHOD, args.KEY, time.Duration(args.Duration)*time.Second)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println(urlStr)
	// 	return nil
	// })
	//
	// type BucketAclOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	KEY    string `help:"key of object"`
	// }
	// RegionR(&BucketAclOption{}, "object-acl", "Get object acl", func(cli cloudprovider.ICloudRegion, args *BucketAclOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	object, err := cloudprovider.GetIObject(bucket, args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println(object.GetAcl())
	// 	return nil
	// })
	//
	// type BucketSetAclOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	KEY    string `help:"key of object"`
	// 	ACL    string `help:"Target acl" choices:"default|private|public-read|public-read-write"`
	// }
	// RegionR(&BucketSetAclOption{}, "object-set-acl", "Get object acl", func(cli cloudprovider.ICloudRegion, args *BucketSetAclOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	object, err := cloudprovider.GetIObject(bucket, args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	err = object.SetAcl(cloudprovider.TBucketACLType(args.ACL))
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type BucketSetWebsiteOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	// 主页
	// 	Index string `help:"main page"`
	// 	// 错误时返回的文档
	// 	ErrorDocument string `help:"error return"`
	// 	// http或https
	// 	Protocol string `help:"force https" choices:"http|https"`
	// }
	// RegionR(&BucketSetWebsiteOption{}, "bucket-set-website", "Set bucket website", func(cli cloudprovider.ICloudRegion, args *BucketSetWebsiteOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	conf := cloudprovider.SBucketWebsiteConf{
	// 		Index:         args.Index,
	// 		ErrorDocument: args.ErrorDocument,
	// 		Protocol:      args.Protocol,
	// 	}
	// 	err = bucket.SetWebsite(conf)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type BucketGetWebsiteConfOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetWebsiteConfOption{}, "bucket-get-website", "Get bucket website", func(cli cloudprovider.ICloudRegion, args *BucketGetWebsiteConfOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	conf, err := bucket.GetWebsiteConf()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintObject(conf)
	// 	return nil
	// })
	//
	// type BucketDeleteWebsiteConfOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketDeleteWebsiteConfOption{}, "bucket-delete-website", "Delete bucket website", func(cli cloudprovider.ICloudRegion, args *BucketDeleteWebsiteConfOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	err = bucket.DeleteWebSiteConf()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type BucketSetCorsOption struct {
	// 	BUCKET         string `help:"name of bucket to put object"`
	// 	AllowedMethods []string
	// 	// 允许的源站，可以设为*
	// 	AllowedOrigins []string
	// 	AllowedHeaders []string
	// 	MaxAgeSeconds  int
	// 	ExposeHeaders  []string
	// 	Id             string
	// }
	// RegionR(&BucketSetCorsOption{}, "bucket-set-cors", "Set bucket cors", func(cli cloudprovider.ICloudRegion, args *BucketSetCorsOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	rule := cloudprovider.SBucketCORSRule{
	// 		AllowedOrigins: args.AllowedOrigins,
	// 		AllowedMethods: args.AllowedMethods,
	// 		AllowedHeaders: args.AllowedHeaders,
	// 		MaxAgeSeconds:  args.MaxAgeSeconds,
	// 		ExposeHeaders:  args.ExposeHeaders,
	// 		Id:             args.Id,
	// 	}
	// 	err = cloudprovider.SetBucketCORS(bucket, []cloudprovider.SBucketCORSRule{rule})
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type BucketGetCorsOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetCorsOption{}, "bucket-get-cors", "Get bucket cors", func(cli cloudprovider.ICloudRegion, args *BucketGetCorsOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	rules, err := bucket.GetCORSRules()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintList(rules, len(rules), 0, len(rules), nil)
	// 	return nil
	// })
	//
	// type BucketDeleteCorsOption struct {
	// 	BUCKET string   `help:"name of bucket to put object"`
	// 	Ids    []string `help:"rule ids to delete"`
	// }
	// RegionR(&BucketDeleteCorsOption{}, "bucket-delete-cors", "Delete bucket cors", func(cli cloudprovider.ICloudRegion, args *BucketDeleteCorsOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	result, err := cloudprovider.DeleteBucketCORS(bucket, args.Ids)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintList(result, len(result), 0, len(result), nil)
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type BucketSetRefererOption struct {
	// 	BUCKET      string `help:"name of bucket to put object"`
	// 	RefererType string `help:"referer type" choices:"Black-List|White-List" default:"Black-List"`
	// 	DomainList  []string
	// 	// 是否允许空refer 访问
	// 	AllowEmptyRefer bool `help:"all empty refer access"`
	// 	Disable         bool
	// }
	// RegionR(&BucketSetRefererOption{}, "bucket-set-referer", "Set bucket referer", func(cli cloudprovider.ICloudRegion, args *BucketSetRefererOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	conf := cloudprovider.SBucketRefererConf{
	// 		DomainList:      args.DomainList,
	// 		RefererType:     args.RefererType,
	// 		AllowEmptyRefer: args.AllowEmptyRefer,
	// 		Enabled:         true,
	// 	}
	// 	if args.Disable {
	// 		conf.Enabled = false
	// 	}
	// 	err = bucket.SetReferer(conf)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	//
	// })
	//
	// type BucketGetPolicyOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetPolicyOption{}, "bucket-get-policy", "get bucket policy", func(cli cloudprovider.ICloudRegion, args *BucketGetPolicyOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	policy, err := bucket.GetPolicy()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintList(policy, len(policy), 0, len(policy), nil)
	// 	return nil
	// })
	//
	// type BucketSetPolicyOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	// 格式主账号id:子账号id
	// 	PrincipalId []string
	// 	// Read|ReadWrite|FullControl
	// 	CannedAction string
	// 	// Allow|Deny
	// 	Effect string
	// 	// 被授权的资源地址
	// 	ResourcePath []string
	// 	// ip 条件
	// 	IpEquals    []string
	// 	IpNotEquals []string
	// }
	// RegionR(&BucketSetPolicyOption{}, "bucket-set-policy", "set bucket policy", func(cli cloudprovider.ICloudRegion, args *BucketSetPolicyOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	opts := cloudprovider.SBucketPolicyStatementInput{}
	// 	opts.CannedAction = args.CannedAction
	// 	opts.Effect = args.Effect
	// 	opts.IpEquals = args.IpEquals
	// 	opts.IpNotEquals = args.IpNotEquals
	// 	opts.ResourcePath = args.ResourcePath
	// 	opts.PrincipalId = args.PrincipalId
	//
	// 	err = bucket.SetPolicy(opts)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	return nil
	// })
	//
	// type BucketDeletePolicyOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// 	Id     []string
	// }
	// RegionR(&BucketDeletePolicyOption{}, "bucket-delete-policy", "delete bucket policy", func(cli cloudprovider.ICloudRegion, args *BucketDeletePolicyOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	result, err := bucket.DeletePolicy(args.Id)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintList(result, len(result), 0, len(result), nil)
	// 	return nil
	// })
	//
	// type BucketGetRefererOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetRefererOption{}, "bucket-get-referer", "get bucket referer", func(cli cloudprovider.ICloudRegion, args *BucketGetRefererOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	conf, err := bucket.GetReferer()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintObject(conf)
	// 	return nil
	// })
	//
	// type BucketGetCdnDomainOption struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetCdnDomainOption{}, "bucket-get-cdn-domains", "get bucket cdn domains", func(cli cloudprovider.ICloudRegion, args *BucketGetCdnDomainOption) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	domains, err := bucket.GetCdnDomains()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintList(domains, len(domains), 0, len(domains), nil)
	// 	return nil
	// })
	//
	// type BucketGetMetadata struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetMetadata{}, "bucket-tag-list", "List bucket tag", func(cli cloudprovider.ICloudRegion, args *BucketGetMetadata) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	meta, err := bucket.GetTags()
	// 	if err != nil {
	// 		return err
	// 	}
	// 	PrintObject(meta)
	// 	return nil
	// })
	//
	// type BucketSetMetadate struct {
	// 	BUCKET  string   `help:"name of bucket to put object"`
	// 	Tags    []string `help:"Tags info, eg: hypervisor=aliyun、os_type=Linux、os_version"`
	// 	Replace bool
	// }
	// RegionR(&BucketSetMetadate{}, "bucket-set-tag", "set bucket tag", func(cli cloudprovider.ICloudRegion, args *BucketSetMetadate) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	tags := map[string]string{}
	// 	for _, tag := range args.Tags {
	// 		pair := strings.Split(tag, "=")
	// 		if len(pair) == 2 {
	// 			tags[pair[0]] = pair[1]
	// 		}
	// 	}
	// 	_, err = cloudprovider.SetBucketTags(context.Background(), bucket, "", tags)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type BucketGetUploads struct {
	// 	BUCKET string `help:"name of bucket to put object"`
	// }
	// RegionR(&BucketGetUploads{}, "bucket-get-uploads", "get bucket uploads", func(cli cloudprovider.ICloudRegion, args *BucketGetUploads) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	uplaods, err := bucket.ListMultipartUploads()
	// 	PrintList(uplaods, len(uplaods), 0, len(uplaods), nil)
	// 	return nil
	// })
	//
	// type BucketObjectDownloadOptions struct {
	// 	BUCKET string `help:"name of bucket"`
	// 	KEY    string `help:"Key of object"`
	// 	Output string `help:"target output, default to stdout"`
	// 	Start  int64  `help:"partial download start"`
	// 	End    int64  `help:"partial download end"`
	// }
	// RegionR(&BucketObjectDownloadOptions{}, "object-download", "Download", func(cli cloudprovider.ICloudRegion, args *BucketObjectDownloadOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	obj, err := cloudprovider.GetIObject(bucket, args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	//
	// 	var rangeOpt *cloudprovider.SGetObjectRange
	// 	if args.Start != 0 || args.End != 0 {
	// 		if args.End <= 0 {
	// 			args.End = obj.GetSizeBytes() - 1
	// 		}
	// 		rangeOpt = &cloudprovider.SGetObjectRange{Start: args.Start, End: args.End}
	// 	}
	// 	output, err := bucket.GetObject(context.Background(), args.KEY, rangeOpt)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	defer output.Close()
	// 	var target io.Writer
	// 	if len(args.Output) == 0 {
	// 		target = os.Stdout
	// 	} else {
	// 		fp, err := os.Create(args.Output)
	// 		if err != nil {
	// 			return err
	// 		}
	// 		defer fp.Close()
	// 		target = fp
	// 	}
	// 	prop, err := streamutils.StreamPipe(output, target, false, nil)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	if len(args.Output) > 0 {
	// 		fmt.Println("Success:", prop.Size, "written")
	// 	}
	// 	return nil
	// })
	//
	// type BucketObjectTempUrlOptions struct {
	// 	BUCKET string `help:"name of bucket"`
	// 	KEY    string `help:"Key of object"`
	// 	Method string `default:"GET" choices:"GET|PUT|POST"`
	// 	Hour   int64  `default:"1"`
	// }
	//
	// RegionR(&BucketObjectTempUrlOptions{}, "object-temp-url", "Show object temp url", func(cli cloudprovider.ICloudRegion, args *BucketObjectTempUrlOptions) error {
	// 	bucket, err := cli.GetIBucketById(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	url, err := bucket.GetTempUrl(args.Method, args.KEY, time.Duration(args.Hour)*time.Hour)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	fmt.Println(url)
	// 	return nil
	// })
	//
	// type BucketObjectCopyOptions struct {
	// 	SRC       string `help:"name of source bucket"`
	// 	SRCKEY    string `help:"Key of source object"`
	// 	DST       string `help:"name of destination bucket"`
	// 	DSTKEY    string `help:"key of destination object"`
	// 	Debug     bool   `help:"show debug info"`
	// 	BlockSize int64  `help:"block size in MB"`
	// 	Native    bool   `help:"Use native copy"`
	//
	// 	ObjectHeaderOptions
	// }
	// RegionR(&BucketObjectCopyOptions{}, "object-copy", "Copy object", func(cli cloudprovider.ICloudRegion, args *BucketObjectCopyOptions) error {
	// 	ctx := context.Background()
	// 	dstBucket, err := cli.GetIBucketByName(args.DST)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	srcBucket, err := cli.GetIBucketByName(args.SRC)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	srcObj, err := cloudprovider.GetIObject(srcBucket, args.SRCKEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	meta := args.ObjectHeaderOptions.Options2Header()
	// 	if args.Native {
	// 		err = dstBucket.CopyObject(ctx, args.DSTKEY, args.SRC, args.SRCKEY, srcObj.GetAcl(), srcObj.GetStorageClass(), meta)
	// 		if err != nil {
	// 			return err
	// 		}
	// 	} else {
	// 		err = cloudprovider.CopyObject(ctx, args.BlockSize*1000*1000, dstBucket, args.DSTKEY, srcBucket, args.SRCKEY, meta, args.Debug)
	// 		if err != nil {
	// 			return err
	// 		}
	// 	}
	// 	fmt.Println("Success!")
	// 	return nil
	// })
	//
	// type ObjectMetaOptions struct {
	// 	BUCKET string `help:"bucket name"`
	// 	KEY    string `help:"object key"`
	// }
	// RegionR(&ObjectMetaOptions{}, "object-meta", "Show object meta header", func(cli cloudprovider.ICloudRegion, args *ObjectMetaOptions) error {
	// 	bucket, err := cli.GetIBucketByName(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	obj, err := cloudprovider.GetIObject(bucket, args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	meta := obj.GetMeta()
	// 	for k, v := range meta {
	// 		fmt.Println(k, ": ", v[0])
	// 	}
	// 	return nil
	// })
	//
	// type ObjectSetMetaOptions struct {
	// 	BUCKET string `help:"bucket name"`
	// 	KEY    string `help:"object key"`
	//
	// 	ObjectHeaderOptions
	// }
	// RegionR(&ObjectSetMetaOptions{}, "object-set-meta", "Set object meta header", func(cli cloudprovider.ICloudRegion, args *ObjectSetMetaOptions) error {
	// 	bucket, err := cli.GetIBucketByName(args.BUCKET)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	obj, err := cloudprovider.GetIObject(bucket, args.KEY)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	meta := args.ObjectHeaderOptions.Options2Header()
	// 	err = obj.SetMeta(context.Background(), meta)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	return nil
	// })
}
